
#import "Controller.h"

#include <stdio.h>

@implementation Controller

void runOneStep(DPSTimedEntry timedEntry, double timeNow, void *data)
{
	[(id)data step];
}

// for future reference:
// asyn_getc() returns char code, EOF or NONE(-2) defined in <geomutil.h>

- displayFrame:(int)frameno
{
    int num;
    
    fprintf(stdout,"(progn");
    fprintf(stdout,"(geometry animate : a%d)\n", frameno);
    fprintf(stdout,"(echo \"1\n\"))\n");
    fflush(stdout);
    fscanf(stdin,"%d",&num);
    if(hiliteFrame) {
        [theMatrix selectCellAt:frameno :0];
	[theMatrix scrollCellToVisible:frameno :0];
    }
    if(commandFlag) fprintf(stdout,"%s",commandString);
    return self;
}

- appDidInit:sender
{
    [animateWindow setAvoidsActivation:YES];
    fps = [fpsField intValue];
    timerEnabled = NO;
    theMode = forward;
    bounceDir = 1;
    [browser setDelegate:self];
    theMatrix = [browser matrixInColumn:0];
    hiliteFrame = NO;
    onceFlag = NO;
    return self;
}

- (int)browser:sender fillMatrix:theMatrix inColumn:(int)column
{
    NXBrowserCell *theCell;
    int i=0;
    
    while (filesbase && *filesbase) {
	[theMatrix addRow];
	theCell = [theMatrix cellAt:i :0];
	[theCell setStringValue:(char *)*filesbase];
	[[theCell setLoaded:YES] setLeaf:YES];
	filesbase++;
	i++;
    }

    return i;
}

- browserCellSelected:sender
{
    int n = [theMatrix selectedRow];
    if(timerEnabled) {
    	DPSRemoveTimedEntry(timer);
	timerEnabled = NO;
    }
    [self displayFrame:n];
    return self;
}

- hiliteCurrentFrame:sender
{
    hiliteFrame = [sender intValue];
    return self;
}

- step
{
    switch(theMode) {
    
	case forward:
	currentFrame++;
	if(currentFrame>=frames) {
	    if(onceFlag) {
	    	onceFlag = NO;
		DPSRemoveTimedEntry(timer);
		timerEnabled = NO;
		currentFrame = frames - 1;
	    }
	else currentFrame = 0;
	}
	break;
	
	case reverse:
	currentFrame--;
	if(currentFrame<0) currentFrame = frames - 1;
	break;
	
	case bounce:
	currentFrame += bounceDir;
	if(currentFrame>=frames) {
	    bounceDir *= -1;
	    if(frames>1) currentFrame += 2*bounceDir;
	    else currentFrame = 0;
	}
	if(currentFrame<0) {
	    bounceDir *= -1;
	    if(frames>1) currentFrame += 2*bounceDir;
	    else currentFrame = 0;
        }
	break;
    }
    
    [self displayFrame:currentFrame];
    
    return self;
}

- bounce:sender
{
    if(!timerEnabled) {
        timer = DPSAddTimedEntry(1./fps, &runOneStep, self, NX_BASETHRESHOLD);
	timerEnabled = YES;
    }
    theMode = bounce;
    return self;
}

- command:sender
{
    [[commandField window] makeKeyAndOrderFront:self];
    return self;
}

- commandEntered:sender
{
    strcpy(commandString,[sender stringValue]);
    commandFlag = YES;
    return self;
}

- readSingleFile:(char *)filename
{
    fprintf(stdout,"(hdefine \"geometry\" a%d < \"%s\")\n", currentFrame, filename);
    fflush(stdout);
    return self;
}

- load:sender
{
    char fullname[512];
    id openpanel = [OpenPanel new];
    NXBrowserCell *theCell;
    
    [NXApp activateSelf:YES];  
    [openpanel allowMultipleFiles:YES];
    //[openpanel setAccessoryView:[accessoryPanel contentView]];
    
    
    if ([openpanel runModal]) {
	files = filesbase = [openpanel filenames];
	directory = [openpanel directory];
	
	frames = 0;
	currentFrame = 0;
	while (files && *files) {
	    //[theMatrix addRow];
	    //theCell = [theMatrix cellAt:currentFrame :0];
	    //[theCell setStringValue:(char *)*files];
	    //[[theCell setLoaded:YES] setLeaf:YES];
	    //[theMatrix display];
	    //[browser displayColumn:0];
	    sprintf(fullname,"%s/%s",directory, (char *)*files);
	    fprintf(stdout,"(hdefine \"geometry\" a%d < \"%s\")\n",
		    currentFrame, fullname);
 	    [self displayFrame:currentFrame];
	    files++;
	    currentFrame++;
	    frames++;
	}
	if(frames) [self displayFrame:0];
	[browser loadColumnZero];
    }
    
    [NXApp deactivateSelf];
    return self;
}

- loop:sender
{
    if(!timerEnabled) {
        timer = DPSAddTimedEntry(1./fps, &runOneStep, self, NX_BASETHRESHOLD);
	timerEnabled = YES;
    }
    return self;
}

- once:sender
{
    onceFlag = YES;
    theMode = forward;
    if(!timerEnabled) {
	currentFrame = -1;
    	timer = DPSAddTimedEntry(1./fps, &runOneStep, self, NX_BASETHRESHOLD);
	timerEnabled = YES;
    }
    return self;
}

- stepdown:sender
{
    currentFrame--;
    if(currentFrame<0) currentFrame = frames-1;
    if(frames) [self displayFrame:currentFrame];
    theMode = reverse;
    bounceDir = -1;
    if(timerEnabled) {
        timerEnabled = NO;
	DPSRemoveTimedEntry(timer);
    }
    return self;
}

- stepup:sender
{
    currentFrame++;
    if(currentFrame>=frames) currentFrame = 0.0;
    if(frames) [self displayFrame:currentFrame];
    theMode = forward;
    bounceDir = 1;
    if(timerEnabled) {
        timerEnabled = NO;
	DPSRemoveTimedEntry(timer);
    }
    return self;
}

- fpsEntered:sender
{
    fps = [fpsField intValue];
    if(timerEnabled) {
        DPSRemoveTimedEntry(timer);
	NXPing(); // Not sure we need this
	DPSAddTimedEntry(1./fps, &runOneStep, self, NX_BASETHRESHOLD);
    }
    return self;
}

@end
